package com.lifeverse.service;

import com.lifeverse.entity.BehaviorPattern;
import com.lifeverse.entity.LifeEntity;
import com.lifeverse.entity.PatternAlert;
import com.lifeverse.entity.enums.AlertSeverity;
import com.lifeverse.entity.enums.AlertStatus;
import com.lifeverse.entity.enums.PatternStatus;
import com.lifeverse.repository.BehaviorPatternRepository;
import com.lifeverse.repository.PatternAlertRepository;
import com.lifeverse.util.JsonUtils;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.math3.stat.descriptive.DescriptiveStatistics;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.time.temporal.ChronoUnit;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 异常行为检测服务
 * 使用多种算法检测生命体的异常行为模式
 */
@Service
@RequiredArgsConstructor
@Slf4j
public class AnomalyDetectionService {

    private final BehaviorPatternRepository behaviorPatternRepository;
    private final PatternAlertRepository patternAlertRepository;
    private final JsonUtils jsonUtils;

    // 异常检测阈值配置
    private static final double ANOMALY_THRESHOLD = 0.7;
    private static final double SEVERE_ANOMALY_THRESHOLD = 0.9;
    private static final int MIN_PATTERN_SAMPLES = 5;
    private static final int LOOKBACK_DAYS = 30;

    /**
     * 检测生命体的异常行为
     */
    @Transactional
    public List<PatternAlert> detectAnomalies(Long lifeEntityId) {
        log.info("开始检测生命体 {} 的异常行为", lifeEntityId);
        
        List<PatternAlert> alerts = new ArrayList<>();
        
        try {
            // 获取最近的行为模式
            List<BehaviorPattern> recentPatterns = getRecentPatterns(lifeEntityId);
            
            if (recentPatterns.size() < MIN_PATTERN_SAMPLES) {
                log.info("生命体 {} 的模式样本不足，跳过异常检测", lifeEntityId);
                return alerts;
            }
            
            // 1. 统计异常检测
            alerts.addAll(detectStatisticalAnomalies(lifeEntityId, recentPatterns));
            
            // 2. 时间序列异常检测
            alerts.addAll(detectTimeSeriesAnomalies(lifeEntityId, recentPatterns));
            
            // 3. 行为偏差检测
            alerts.addAll(detectBehaviorDeviations(lifeEntityId, recentPatterns));
            
            // 4. 频率异常检测
            alerts.addAll(detectFrequencyAnomalies(lifeEntityId, recentPatterns));
            
            // 保存检测到的预警
            if (!alerts.isEmpty()) {
                alerts = patternAlertRepository.saveAll(alerts);
                log.info("为生命体 {} 生成了 {} 个异常预警", lifeEntityId, alerts.size());
            }
            
        } catch (Exception e) {
            log.error("检测生命体 {} 异常行为时发生错误", lifeEntityId, e);
        }
        
        return alerts;
    }

    /**
     * 统计异常检测
     * 使用Z-score方法检测统计异常
     */
    private List<PatternAlert> detectStatisticalAnomalies(Long lifeEntityId, List<BehaviorPattern> patterns) {
        List<PatternAlert> alerts = new ArrayList<>();
        
        try {
            // 按模式类型分组
            Map<String, List<BehaviorPattern>> patternsByType = patterns.stream()
                    .collect(Collectors.groupingBy(p -> p.getPatternType().name()));
            
            for (Map.Entry<String, List<BehaviorPattern>> entry : patternsByType.entrySet()) {
                String patternType = entry.getKey();
                List<BehaviorPattern> typePatterns = entry.getValue();
                
                if (typePatterns.size() < MIN_PATTERN_SAMPLES) continue;
                
                // 计算置信度的统计特征
                double[] confidenceScores = typePatterns.stream()
                        .mapToDouble(BehaviorPattern::getConfidenceScore)
                        .toArray();
                
                DescriptiveStatistics stats = new DescriptiveStatistics(confidenceScores);
                double mean = stats.getMean();
                double stdDev = stats.getStandardDeviation();
                
                // 检测异常值
                for (BehaviorPattern pattern : typePatterns) {
                    double zScore = Math.abs((pattern.getConfidenceScore() - mean) / stdDev);
                    
                    if (zScore > 2.5) { // 2.5个标准差以外认为是异常
                        PatternAlert alert = createAlert(
                                pattern,
                                lifeEntityId,
                                "统计异常检测",
                                String.format("模式类型 %s 的置信度异常，Z-score: %.2f", patternType, zScore),
                                zScore > 3.0 ? AlertSeverity.HIGH : AlertSeverity.MEDIUM,
                                zScore / 3.0
                        );
                        alerts.add(alert);
                    }
                }
            }
            
        } catch (Exception e) {
            log.error("统计异常检测时发生错误", e);
        }
        
        return alerts;
    }

    /**
     * 时间序列异常检测
     * 检测模式在时间维度上的异常变化
     */
    private List<PatternAlert> detectTimeSeriesAnomalies(Long lifeEntityId, List<BehaviorPattern> patterns) {
        List<PatternAlert> alerts = new ArrayList<>();
        
        try {
            // 按时间排序
            patterns.sort(Comparator.comparing(BehaviorPattern::getLastDetectedAt));
            
            // 检测频率突变
            alerts.addAll(detectFrequencySpikes(lifeEntityId, patterns));
            
            // 检测置信度趋势异常
            alerts.addAll(detectConfidenceTrendAnomalies(lifeEntityId, patterns));
            
            // 检测模式消失异常
            alerts.addAll(detectPatternDisappearance(lifeEntityId, patterns));
            
        } catch (Exception e) {
            log.error("时间序列异常检测时发生错误", e);
        }
        
        return alerts;
    }

    /**
     * 检测频率突增
     */
    private List<PatternAlert> detectFrequencySpikes(Long lifeEntityId, List<BehaviorPattern> patterns) {
        List<PatternAlert> alerts = new ArrayList<>();
        
        // 计算每日模式频率
        Map<String, Integer> dailyFrequency = new HashMap<>();
        
        for (BehaviorPattern pattern : patterns) {
            String date = pattern.getLastDetectedAt().toLocalDate().toString();
            dailyFrequency.merge(date, pattern.getFrequency(), Integer::sum);
        }
        
        if (dailyFrequency.size() < 3) return alerts;
        
        List<Integer> frequencies = new ArrayList<>(dailyFrequency.values());
        DescriptiveStatistics stats = new DescriptiveStatistics(frequencies.stream().mapToDouble(Integer::doubleValue).toArray());
        
        double mean = stats.getMean();
        double stdDev = stats.getStandardDeviation();
        
        // 检查最近的频率是否异常高
        Integer recentFrequency = frequencies.get(frequencies.size() - 1);
        if (recentFrequency > mean + 2 * stdDev) {
            PatternAlert alert = createAlert(
                    null,
                    lifeEntityId,
                    "频率突增异常",
                    String.format("检测到模式频率突增，当前频率: %d，平均频率: %.1f", recentFrequency, mean),
                    AlertSeverity.MEDIUM,
                    Math.min((recentFrequency - mean) / (2 * stdDev), 1.0)
            );
            alerts.add(alert);
        }
        
        return alerts;
    }

    /**
     * 检测置信度趋势异常
     */
    private List<PatternAlert> detectConfidenceTrendAnomalies(Long lifeEntityId, List<BehaviorPattern> patterns) {
        List<PatternAlert> alerts = new ArrayList<>();
        
        if (patterns.size() < 5) return alerts;
        
        // 计算置信度的移动平均和趋势
        List<Double> confidenceScores = patterns.stream()
                .map(BehaviorPattern::getConfidenceScore)
                .collect(Collectors.toList());
        
        // 计算最近5个模式的平均置信度
        double recentAvg = confidenceScores.subList(Math.max(0, confidenceScores.size() - 5), confidenceScores.size())
                .stream().mapToDouble(Double::doubleValue).average().orElse(0.0);
        
        // 计算历史平均置信度
        double historicalAvg = confidenceScores.stream().mapToDouble(Double::doubleValue).average().orElse(0.0);
        
        // 如果最近的置信度显著下降
        if (recentAvg < historicalAvg * 0.7) {
            PatternAlert alert = createAlert(
                    null,
                    lifeEntityId,
                    "置信度下降异常",
                    String.format("检测到置信度显著下降，最近平均: %.2f，历史平均: %.2f", recentAvg, historicalAvg),
                    AlertSeverity.MEDIUM,
                    (historicalAvg - recentAvg) / historicalAvg
            );
            alerts.add(alert);
        }
        
        return alerts;
    }

    /**
     * 检测模式消失异常
     */
    private List<PatternAlert> detectPatternDisappearance(Long lifeEntityId, List<BehaviorPattern> patterns) {
        List<PatternAlert> alerts = new ArrayList<>();
        
        LocalDateTime now = LocalDateTime.now();
        LocalDateTime threeDaysAgo = now.minus(3, ChronoUnit.DAYS);
        
        // 查找历史上活跃但最近消失的模式
        List<BehaviorPattern> historicalPatterns = behaviorPatternRepository.findByLifeEntityId(lifeEntityId);
        
        for (BehaviorPattern historical : historicalPatterns) {
            if (historical.getStatus() == PatternStatus.ACTIVE && 
                historical.getLastDetectedAt().isBefore(threeDaysAgo) &&
                historical.getFrequency() > 10) { // 历史上比较活跃的模式
                
                PatternAlert alert = createAlert(
                        historical,
                        lifeEntityId,
                        "模式消失异常",
                        String.format("活跃模式 %s 已消失超过3天", historical.getPatternName()),
                        AlertSeverity.LOW,
                        0.6
                );
                alerts.add(alert);
            }
        }
        
        return alerts;
    }

    /**
     * 行为偏差检测
     * 检测与历史行为基线的偏差
     */
    private List<PatternAlert> detectBehaviorDeviations(Long lifeEntityId, List<BehaviorPattern> patterns) {
        List<PatternAlert> alerts = new ArrayList<>();
        
        try {
            // 建立行为基线
            Map<String, Double> baseline = establishBehaviorBaseline(lifeEntityId);
            
            // 计算当前行为特征
            Map<String, Double> currentBehavior = calculateCurrentBehaviorFeatures(patterns);
            
            // 比较偏差
            for (Map.Entry<String, Double> entry : currentBehavior.entrySet()) {
                String feature = entry.getKey();
                Double currentValue = entry.getValue();
                Double baselineValue = baseline.get(feature);
                
                if (baselineValue != null && baselineValue > 0) {
                    double deviation = Math.abs(currentValue - baselineValue) / baselineValue;
                    
                    if (deviation > 0.5) { // 偏差超过50%
                        PatternAlert alert = createAlert(
                                null,
                                lifeEntityId,
                                "行为偏差异常",
                                String.format("特征 %s 偏离基线 %.1f%%，当前值: %.2f，基线值: %.2f", 
                                        feature, deviation * 100, currentValue, baselineValue),
                                deviation > 0.8 ? AlertSeverity.HIGH : AlertSeverity.MEDIUM,
                                Math.min(deviation, 1.0)
                        );
                        alerts.add(alert);
                    }
                }
            }
            
        } catch (Exception e) {
            log.error("行为偏差检测时发生错误", e);
        }
        
        return alerts;
    }

    /**
     * 频率异常检测
     */
    private List<PatternAlert> detectFrequencyAnomalies(Long lifeEntityId, List<BehaviorPattern> patterns) {
        List<PatternAlert> alerts = new ArrayList<>();
        
        try {
            // 按模式类型分组检测频率异常
            Map<String, List<BehaviorPattern>> patternsByType = patterns.stream()
                    .collect(Collectors.groupingBy(p -> p.getPatternType().name()));
            
            for (Map.Entry<String, List<BehaviorPattern>> entry : patternsByType.entrySet()) {
                String patternType = entry.getKey();
                List<BehaviorPattern> typePatterns = entry.getValue();
                
                if (typePatterns.size() < 3) continue;
                
                // 计算频率统计
                int[] frequencies = typePatterns.stream().mapToInt(BehaviorPattern::getFrequency).toArray();
                DescriptiveStatistics stats = new DescriptiveStatistics(Arrays.stream(frequencies).asDoubleStream().toArray());
                
                double mean = stats.getMean();
                double stdDev = stats.getStandardDeviation();
                
                // 检测异常频率
                for (BehaviorPattern pattern : typePatterns) {
                    double zScore = Math.abs((pattern.getFrequency() - mean) / stdDev);
                    
                    if (zScore > 2.0) {
                        PatternAlert alert = createAlert(
                                pattern,
                                lifeEntityId,
                                "频率异常",
                                String.format("模式 %s 频率异常，频率: %d，平均频率: %.1f", 
                                        pattern.getPatternName(), pattern.getFrequency(), mean),
                                zScore > 3.0 ? AlertSeverity.HIGH : AlertSeverity.MEDIUM,
                                Math.min(zScore / 3.0, 1.0)
                        );
                        alerts.add(alert);
                    }
                }
            }
            
        } catch (Exception e) {
            log.error("频率异常检测时发生错误", e);
        }
        
        return alerts;
    }

    /**
     * 建立行为基线
     */
    private Map<String, Double> establishBehaviorBaseline(Long lifeEntityId) {
        Map<String, Double> baseline = new HashMap<>();
        
        LocalDateTime thirtyDaysAgo = LocalDateTime.now().minus(LOOKBACK_DAYS, ChronoUnit.DAYS);
        List<BehaviorPattern> historicalPatterns = behaviorPatternRepository
                .findActivePatternsSince(thirtyDaysAgo)
                .stream()
                .filter(p -> p.getLifeEntityId().equals(lifeEntityId))
                .collect(Collectors.toList());
        
        if (historicalPatterns.isEmpty()) {
            return baseline;
        }
        
        // 计算基线特征
        baseline.put("avg_confidence", historicalPatterns.stream()
                .mapToDouble(BehaviorPattern::getConfidenceScore)
                .average().orElse(0.0));
        
        baseline.put("avg_frequency", historicalPatterns.stream()
                .mapToDouble(BehaviorPattern::getFrequency)
                .average().orElse(0.0));
        
        baseline.put("pattern_diversity", (double) historicalPatterns.stream()
                .map(p -> p.getPatternType().name())
                .collect(Collectors.toSet()).size());
        
        baseline.put("avg_anomaly_score", historicalPatterns.stream()
                .filter(p -> p.getAnomalyScore() != null)
                .mapToDouble(BehaviorPattern::getAnomalyScore)
                .average().orElse(0.0));
        
        return baseline;
    }

    /**
     * 计算当前行为特征
     */
    private Map<String, Double> calculateCurrentBehaviorFeatures(List<BehaviorPattern> patterns) {
        Map<String, Double> features = new HashMap<>();
        
        if (patterns.isEmpty()) {
            return features;
        }
        
        features.put("avg_confidence", patterns.stream()
                .mapToDouble(BehaviorPattern::getConfidenceScore)
                .average().orElse(0.0));
        
        features.put("avg_frequency", patterns.stream()
                .mapToDouble(BehaviorPattern::getFrequency)
                .average().orElse(0.0));
        
        features.put("pattern_diversity", (double) patterns.stream()
                .map(p -> p.getPatternType().name())
                .collect(Collectors.toSet()).size());
        
        features.put("avg_anomaly_score", patterns.stream()
                .filter(p -> p.getAnomalyScore() != null)
                .mapToDouble(BehaviorPattern::getAnomalyScore)
                .average().orElse(0.0));
        
        return features;
    }

    /**
     * 获取最近的模式
     */
    private List<BehaviorPattern> getRecentPatterns(Long lifeEntityId) {
        LocalDateTime since = LocalDateTime.now().minus(LOOKBACK_DAYS, ChronoUnit.DAYS);
        return behaviorPatternRepository.findActivePatternsSince(since)
                .stream()
                .filter(p -> p.getLifeEntityId().equals(lifeEntityId))
                .collect(Collectors.toList());
    }

    /**
     * 创建预警
     */
    private PatternAlert createAlert(BehaviorPattern pattern, Long lifeEntityId, String title, 
                                   String description, AlertSeverity severity, double alertScore) {
        PatternAlert alert = new PatternAlert();
        alert.setPatternId(pattern != null ? pattern.getId() : null);
        alert.setLifeEntityId(lifeEntityId);
        alert.setTitle(title);
        alert.setDescription(description);
        alert.setSeverity(severity);
        alert.setStatus(AlertStatus.NEW);
        alert.setTriggeredAt(LocalDateTime.now());
        alert.setAlertScore(Math.min(alertScore, 1.0));
        
        return alert;
    }

    /**
     * 批量检测所有生命体的异常
     */
    @Transactional
    public void detectAllAnomalies() {
        log.info("开始批量检测所有生命体的异常行为");
        
        try {
            // 获取所有活跃的生命体ID
            List<Long> activeLifeEntityIds = behaviorPatternRepository.findActivePatternsSince(
                    LocalDateTime.now().minus(1, ChronoUnit.DAYS))
                    .stream()
                    .map(BehaviorPattern::getLifeEntityId)
                    .distinct()
                    .collect(Collectors.toList());
            
            int totalAlerts = 0;
            for (Long lifeEntityId : activeLifeEntityIds) {
                List<PatternAlert> alerts = detectAnomalies(lifeEntityId);
                totalAlerts += alerts.size();
            }
            
            log.info("批量异常检测完成，共检测 {} 个生命体，生成 {} 个预警", 
                    activeLifeEntityIds.size(), totalAlerts);
            
        } catch (Exception e) {
            log.error("批量异常检测时发生错误", e);
        }
    }
}